/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
/* vi: set expandtab shiftwidth=4 tabstop=4: */

#include <stdint.h>
#include "XorHashMacro.h"

/** \file ThomasWangHash32_Jan2007
 *
 * A new hash algorithm by Thomas Wang, as described
 * http://www.concentric.net/~Ttwang/tech/inthash.htm
 * "Version 3.1", dated Jan 2007
 *
 * It appears search for hash functions is done in Java
 * which doesnt quite match what would be optimal in C/C++
 * An equivalent, but faster version is presented in
 * ThomasWangHash32_Jan2007_alt
 *
 */

class ThomasWangHash32_Jan2007
{
public:
    const char* name() const
    {
        return "ThomasWang_Jan2007";
    }

    uint32_t hash32(uint32_t key) const
    {
        key = ~key + (key << 15); // key = (key << 15) - key - 1;
        key = key ^ (key >> 12);
        key = key + (key << 2);
        key = key ^ (key >> 4);
        key = key * 2057; // key = (key + (key << 3)) + (key << 11);
        key = key ^ (key >> 16);
        return key;
    }

    XORHASH
};

/** \brief alternative implementation of ThomasWangHash32_Jan2007
 *
 *
 */
class ThomasWangHash32_Jan2007_alt
{
public:
    const char* name() const
    {
        return "ThomasWang_Jan2007_alt";
    }

    uint32_t hash32(uint32_t key) const
    {
        // no difference here
        key = ~key + (key << 15); // key = (key << 15) - key - 1;

        key = key ^ (key >> 12);
        key = key + (key << 2);
        key = key ^ (key >> 4);

        // most C compilers will find the later expression fast
        //  while key*2057 will use general multiplication (slow)
        key = /* key * 2057; */ (key + (key << 3)) + (key << 11);

        key = key ^ (key >> 16);
        return key;
    }

    XORHASH
};

